package com.liudadan.service.impl;

import com.liudadan.dao.StudentDao;
import com.liudadan.service.StudentService;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Service;
import org.springframework.transaction.annotation.Isolation;
import org.springframework.transaction.annotation.Propagation;
import org.springframework.transaction.annotation.Transactional;
@Transactional
@Service
public class StudentServiceImpl implements StudentService {
    /**
     *
     * @Transactional: 作用（声明式）添加以后，表明当前的类的方法需要事务
     *
     * 细节1：注解的位置 @Target({ElementType.TYPE, ElementType.METHOD})
     *        类上  ： 添加到类上，类下的所有方法都添加了事务（推荐）
     *        方法上： 只有当前方法添加事务
     *        冲突： 类和方法都添加，方法生效....
     * 细节2： boolean readOnly() default false;  只读模式 默认是非只读
     *        true: 事务中只能查询，不能修改 | 包含查询报错：Connection is read-only. Queries leading to data modification are not allowed
     *        false: 可以查询，可以修改
     *        @Transactional(readOnly = true)场景： 1. 类上添加了非只读的事务 2. 内部查询的方法上添加只读模式事务 （只读模式效率更快，查询更快）
     * 细节3： timeout = -1 事务永远不超时 TransactionTimedOutException
     *        timeout = 3 3秒 超过3秒就会抛出异常
     *        限制一个事务执行的最大时间
     * 细节4： 事务的隔离级别 Isolation isolation() default Isolation.DEFAULT;
     *        mysql 第三个 REPEATABLE_READ
     * 细节5： 指定回滚异常和不回滚异常
     *        默认： @Transactional只有发生运行时异常才回滚 RuntimeException
     *        为啥FileNotFoundException不回滚，不在指定的异常范围内
     *        设置回滚异常：rollbackFor = Exception.class
     *        设置异常不回滚： noRollbackFor noRollbackFor = FileNotFoundException.class
     *        注意： noRollbackFor指定的异常一定在 rollbackFor范围内
     *  细节6：传播行为 Propagation propagation() default Propagation.REQUIRED;
     *        什么是传播行为,最好是哪种行为？？？
     *        指的多个业务方法调用，每个业务方法本身就是一个事务，事务的传播行为会决定被调用的业务的事务是否在加入父事务中！！
     *        推荐被调用的service加入到调用service的事务，最终形成一个事务！！ 保证宏观角度的事务一致性！！
     *        是子业务方法添加传播行为属性决定！！ Propagation propagation() default Propagation.REQUIRED; 【加入到父事务中】
     *                         aservice
     *        controller          |              决定bservice是否加入到aservice的事务！
     *                         bservice（传播行为）
     *        Propagation.REQUIRED: 必须的,子业务方法必须在事务中执行，父方法中有事务，加入到父方法的事务，如果没有，自己独立创建！！
     *        Propagation.REQUIRES_NEW： 不管父方法是否有事务，我们都是会使用独立的事务（3个事务）
     *        Propagation.SUPPORTS： 父方法有事务，我就加入，父方法没有事务，我也没有事务执行！！！
     *        Propagation.NOT_SUPPORTED： 不管父方法有没有事务，我都不会在事务中执行！！！
     *        Propagation.MANDATORY： 父方法必须有事务，有我正常加入！没有，我抛异常！！
     *        Propagation.NEVER： 必须在无事务的环境执行，父方法没有事务，咱们正常没事务执行，有事务了，我抛出异常！！！
     *
     */
    @Autowired
    private StudentDao studentDao;
    @Override
    @Transactional(timeout = 2,readOnly = false,rollbackFor = Exception.class,isolation = Isolation.READ_COMMITTED)
    public void changeNameAndGender() {
        studentDao.updateGenderById("妖",1);
        System.out.println("-------------");
        try {
            Thread.sleep(2010L);
        } catch (InterruptedException e) {
            throw new RuntimeException(e);
        }
        studentDao.updateNameById("驴蛋蛋",1);

    }
    @Transactional(propagation = Propagation.REQUIRED)
    public void changeName(){
        System.out.println("changeName");
        studentDao.updateNameById("刘大", 1);
    }
    @Transactional(propagation = Propagation.REQUIRED)
    public void changeGender(){
        System.out.println("changeGender");
        studentDao.updateGenderById("妖", 1);
    }
}
